(function (global, factory) {
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('lodash/cloneDeep')) :
  typeof define === 'function' && define.amd ? define(['exports', 'lodash/cloneDeep'], factory) :
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.micro = {}, global._cloneDeep));
})(this, (function (exports, _cloneDeep) { 'use strict';

  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

  var _cloneDeep__default = /*#__PURE__*/_interopDefaultLegacy(_cloneDeep);

  const getBaseUrl = (context) => {
      var location = window.document.location;
      var pagePath = location.pathname;
      context = context || "";
      if (context != "") {
          var pos = pagePath.indexOf("/" + context);
          context = pos > -1 ? context : "";
          return location.protocol + "//" + location.host + "/" + context;
      }
      else {
          return location.protocol + "//" + location.host;
      }
  };
  function getHtmlContent(Url) {
      return new Promise((resolve, reject) => {
          fetch(Url).then(res => {
              resolve(res.text());
          }).catch(err => {
              reject(err);
          });
      });
  }

  const changeStringToDom = async (baseUrl, html, name) => {
      const contain = document.createElement('div');
      contain.id = '_esbuild_micro_' + name;
      contain.innerHTML = html;
      const jsData = await getChangeJsModule(baseUrl, contain);
      const cssData = await getChangeCssModule(baseUrl, contain);
      return { contain, jsData, cssData };
  };
  const getChangeJsModule = async (baseUrl, contain) => {
      const moduleTags = contain.querySelectorAll('script[type=module]');
      const modulePreload = contain.querySelectorAll('link[rel=modulepreload]');
      const app = [];
      for (let i = 0; i < modulePreload.length; i++) {
          const moduleTag = modulePreload[i];
          const name = moduleTag.href.substring(moduleTag.href.lastIndexOf('/') + 1);
          const href = moduleTag.href.replace(getBaseUrl(""), baseUrl);
          app.push({ name: name, url: href, content: "" });
          contain.removeChild(moduleTag);
      }
      for (let i = 0; i < moduleTags.length; i++) {
          const moduleTag = moduleTags[i];
          const name = moduleTag.src.substring(moduleTag.src.lastIndexOf('/') + 1);
          const src = moduleTag.src.replace(getBaseUrl(""), baseUrl);
          app.push({ name: name, url: src, content: "" });
          contain.removeChild(moduleTag);
      }
      console.log('app', { app });
      return app;
  };
  const getChangeCssModule = async (baseUrl, contain) => {
      const moduleTags = contain.querySelectorAll('link[rel=stylesheet]');
      if (!moduleTags || !moduleTags.length) {
          return;
      }
      const app = [];
      for (let i = 0; i < moduleTags.length; i++) {
          const moduleTag = moduleTags[i];
          const name = moduleTag.href.substring(moduleTag.href.lastIndexOf('/') + 1);
          const href = moduleTag.href.replace(getBaseUrl(""), baseUrl);
          app.push({ name: name, url: href });
          await loadReplaceCss(contain, moduleTag, href, name);
      }
      return app;
  };
  const loadReplaceCss = async (contain, moduleTag, url, keyId) => {
      const css = await getHtmlContent(url);
      const style = document.createElement('style');
      style.id = keyId;
      style.innerHTML = css;
      moduleTag.removeAttribute('href');
      contain.insertBefore(style, moduleTag);
      contain.removeChild(moduleTag);
  };

  var SysMsgType;
  (function (SysMsgType) {
      SysMsgType["js"] = "js";
      SysMsgType["network"] = "network";
      SysMsgType["res"] = "res";
      SysMsgType["performance"] = "performance";
  })(SysMsgType || (SysMsgType = {}));
  var LOGLEVEL;
  (function (LOGLEVEL) {
      LOGLEVEL["debug"] = "debug";
      LOGLEVEL["error"] = "error";
      LOGLEVEL["info"] = "info";
      LOGLEVEL["warn"] = "warn";
      LOGLEVEL["assert"] = "assert";
      LOGLEVEL["clear"] = "clear";
  })(LOGLEVEL || (LOGLEVEL = {}));
  var STYLETYPE;
  (function (STYLETYPE) {
      STYLETYPE["css"] = "%c";
      STYLETYPE["number"] = "%d";
      STYLETYPE["dom"] = "%o";
      STYLETYPE["object"] = "%O";
  })(STYLETYPE || (STYLETYPE = {}));
  var MESSAGESTYLE;
  (function (MESSAGESTYLE) {
      MESSAGESTYLE["debug"] = "color: #FFCCFF;font-size: 12px;text-decoration: underline;";
      MESSAGESTYLE["error"] = "color: #990033;font-size: 12px;font-weight: bold;text-decoration: underline;";
      MESSAGESTYLE["info"] = "color: #33FF33;font-size: 12px;text-decoration: underline;";
      MESSAGESTYLE["warn"] = "color: #FFCC00;font-size: 12px;font-weight: bold;text-decoration: underline;";
      MESSAGESTYLE["assert"] = "color: #99FFFF;font-size: 12px;font-weight: bold;text-decoration: underline;";
      MESSAGESTYLE["clear"] = "color: #3366FF;font-size: 12px;font-weight: bold;";
      MESSAGESTYLE["moudle"] = "color: #FF66FF;font-size: 12px;font-weight: bold;";
  })(MESSAGESTYLE || (MESSAGESTYLE = {}));
  class ConsoleLogger {
      logData = {
          moudle: '',
          level: LOGLEVEL.info,
          styleType: STYLETYPE.css
      };
      console;
      constructor(moudle, con) {
          this.logData.moudle = moudle;
          this.console = con || window.console;
      }
      warn(message, ...argc) {
          const level = LOGLEVEL.error;
          const style = STYLETYPE.css;
          if (window.__POWERED_BY_MICO__.debugger) {
              const logArgs = [`${STYLETYPE.css}[${this.logData.moudle}]-[${message}]-{${style}}`, MESSAGESTYLE[level], ...argc];
              this.console[LOGLEVEL[level]](...logArgs);
          }
      }
      log(message, loglevel, ...argc) {
          let level;
          if (typeof loglevel === 'object') {
              level = LOGLEVEL.info;
              argc.push(loglevel);
          }
          else if (loglevel && MESSAGESTYLE[loglevel]) {
              level = loglevel || this.logData.level;
          }
          else {
              level = LOGLEVEL.info;
              argc.push(loglevel);
          }
          const style = this.logData.styleType;
          if (window.__POWERED_BY_MICO__.debugger) {
              let logArgs = [`${STYLETYPE.css}[${this.logData.moudle}]-${style}[${message}]`, MESSAGESTYLE.moudle, MESSAGESTYLE[level], ...argc];
              switch (style) {
                  case STYLETYPE.dom:
                      logArgs = [`${STYLETYPE.css}[${this.logData.moudle}]-[${message}]-{${style}}`, MESSAGESTYLE[level], ...argc];
                      break;
                  case STYLETYPE.object:
                      logArgs = [`${STYLETYPE.css}[${this.logData.moudle}]-[${message}]-{${style}}`, MESSAGESTYLE[level], ...argc];
                      break;
              }
              switch (level) {
                  case LOGLEVEL.assert:
                      this.console[LOGLEVEL.assert](...argc, `${this.logData.moudle}:${style + message}`, MESSAGESTYLE.assert);
                      break;
                  default:
                      this.console[LOGLEVEL[level]](...logArgs);
                      break;
              }
          }
      }
  }
  new ConsoleLogger('global', console);

  const console$3 = new ConsoleLogger('微应用-主应用-App类');
  const activeApp = async (app) => {
      const dic = window.__POWERED_BY_MICO__;
      console$3.log('开始激活微应用');
      if (dic.partitionAppDic[app.name]) {
          dic.activeAppDic[app.name] = _cloneDeep__default["default"](dic.partitionAppDic[app.name]);
          document.getElementById(app.domId.replace('#', '')).appendChild(app.htmlElement);
          if (dic.partitionAppDic[app.name].clientLife) {
              dic.partitionAppDic[app.name].clientLife.mount({ container: app.htmlElement });
          }
          delete dic.partitionAppDic[app.name];
          return false;
      }
      else {
          if (!document.getElementById(app.domId.replace('#', '')).querySelector('#' + app.htmlElement.id)) {
              document.getElementById(app.domId.replace('#', '')).appendChild(app.htmlElement);
              await app.execApp();
              app.htmlElement = document.getElementById(app.htmlElement.id);
              dic.activeAppDic[app.name].htmlElement = document.getElementById(app.htmlElement.id);
          }
          else {
              console$3.log('执行激活微应用，单当前应用未unmont');
              return false;
          }
          return true;
      }
  };
  const partitionApp = async (app) => {
      const dic = window.__POWERED_BY_MICO__;
      if (dic.activeAppDic[app.name] && !dic.partitionAppDic[app.name]) {
          try {
              dic.partitionAppDic[app.name] = _cloneDeep__default["default"](dic.activeAppDic[app.name]);
              delete dic.activeAppDic[app.name];
              const parent = document.getElementById(app.htmlElement.id).parentElement;
              parent.removeChild(app.htmlElement);
              console$3.log('沙箱微应用成功', { partitionApp: dic.partitionAppDic[app.name] });
          }
          catch (e) {
              return;
          }
      }
  };
  class App {
      baseUrl;
      name;
      domId;
      appJs;
      appCss;
      htmlContent;
      htmlElement;
      constructor(param) {
          Object.keys(param).forEach((key) => {
              this[key] = param[key];
          });
      }
      bootstrap = () => {
          const dic = window.__POWERED_BY_MICO__;
          if (dic.activeAppDic[this.name].clientLife && dic.activeAppDic[this.name].clientLife.bootstrap) {
              dic.activeAppDic[this.name].clientLife.bootstrap({ container: this.htmlElement });
              console$3.log('微应用-子应用bootstrap成功', { name: this.name });
          }
          console$3.log('bootstrap成功', { name: this.name });
      };
      mount = () => {
          const dic = window.__POWERED_BY_MICO__;
          activeApp(this).then(res => {
              if (res) {
                  if (dic.activeAppDic[this.name].clientLife && dic.activeAppDic[this.name].clientLife.mount) {
                      const props = { container: this.htmlElement };
                      if (dic.globalState) {
                          props.globalState != dic.globalState;
                      }
                      dic.activeAppDic[this.name].clientLife.mount(props);
                      console$3.log('微应用-子应用mount成功', { name: this.name });
                  }
              }
              console$3.log('mount成功', { name: this.name });
          });
          console$3.log('激活微应用成功');
      };
      unmount = () => {
          const dic = window.__POWERED_BY_MICO__;
          if (dic.activeAppDic[this.name].clientLife && dic.activeAppDic[this.name].clientLife.unmount) {
              dic.activeAppDic[this.name].clientLife.unmount({ container: this.htmlElement });
              console$3.log('微应用-子应用unmount成功', { name: this.name });
          }
          partitionApp(this);
          console$3.log('unmount成功', { name: this.name });
      };
      distory = () => {
          const dic = window.__POWERED_BY_MICO__;
          this.htmlContent = '';
          const name = this.name;
          this.htmlElement.parentElement.removeChild(this.htmlElement);
          if (dic.activeAppDic[this.name] && dic.activeAppDic[this.name].clientLife && dic.activeAppDic[this.name].clientLife.unmount) {
              dic.activeAppDic[this.name].clientLife.unmount({ container: this.htmlElement });
          }
          if (dic.partitionAppDic[this.name] && dic.partitionAppDic[this.name].clientLife && dic.partitionAppDic[this.name].clientLife.unmount) {
              dic.partitionAppDic[this.name].clientLife.unmount({ container: this.htmlElement });
          }
          this.htmlElement.innerHTML = "";
          delete window.__POWERED_BY_MICO__.activeAppDic[this.name];
          delete window.__POWERED_BY_MICO__.partitionAppDic[this.name];
          for (let ss in this) {
              delete this[ss];
          }
          console$3.log('distory成功', { name });
      };
      clientLife;
      execApp = async () => {
          try {
              const proxy = window.__POWERED_BY_MICO__.clientAppDicProxy;
              if (!proxy[this.name]) {
                  proxy[this.name] = {};
              }
              for (let i = 0; i < this.appJs.length; i++) {
                  if (proxy[this.name][this.appJs[i].name] && proxy[this.name][this.appJs[i].name].default) {
                      proxy[this.name][this.appJs[i].name].default.default.mount({ container: this.htmlElement });
                      return;
                  }
                  proxy[this.name][this.appJs[i].name] = await (async function (window, url) { const res = await import(url); return res; })(proxy, this.appJs[i].url);
              }
              console$3.log('execApp-执行动态import结束', { name: this.name });
          }
          catch (e) {
              console$3.warn('加载出错', SysMsgType.js, { error: e });
              throw new Error('执行子应用失败');
          }
      };
  }

  const console$2 = new ConsoleLogger('微应用-主应用');
  const start = (debug = true) => {
      window.__POWERED_BY_MICO__ = { activeAppDic: {}, partitionAppDic: {}, clientAppDicProxy: {}, debugger: debug, globalState: {} };
      console$2.log('开启微应用-主应用初始化');
  };
  const loadMicro = async (param) => {
      const dic = window.__POWERED_BY_MICO__;
      try {
          if (dic.partitionAppDic[param.name]) {
              await activeApp(dic.partitionAppDic[param.name]);
              return dic.activeAppDic[param.name];
          }
          if (dic.activeAppDic[param.name]) {
              const app_tmp = dic.activeAppDic[param.name];
              document.getElementById(app_tmp.domId.replace('#', '')).innerHTML = "";
              document.getElementById(app_tmp.domId.replace('#', '')).appendChild(app_tmp.htmlElement);
              return app_tmp;
          }
          const html = await getHtmlContent(param.baseUrl);
          const htmlinfo = await changeStringToDom(param.baseUrl, html, param.name);
          const app = new App({
              name: param.name, appJs: htmlinfo.jsData, appCss: htmlinfo.cssData, domId: param.domId,
              htmlContent: html, baseUrl: param.baseUrl, htmlElement: htmlinfo.contain
          });
          dic.activeAppDic[param.name] = app;
          console$2.log('加载微引用成功,后续将执行子应用microClientBind', { app: { ...dic.activeAppDic[param.name] } });
          app.bootstrap();
          app.mount();
          return app;
      }
      catch (e) {
          console$2.warn('加载子应用失败', { e });
          if (dic.activeAppDic[param.name]) {
              delete dic.activeAppDic[param.name];
          }
          throw new Error("加载子应用失败");
      }
  };

  const console$1 = new ConsoleLogger('微应用-子应用');
  const microClientBind = (name, props) => {
      if (window.__POWERED_BY_MICO__) {
          try {
              const dic = window.__POWERED_BY_MICO__;
              dic.activeAppDic[name].clientLife = { bootstrap: props.bootstrap, mount: props.mount, unmount: props.unmount };
              microClientBind.default = { bootstrap: props.bootstrap, mount: props.mount, unmount: props.unmount };
              console$1.log('执行子应用microClientBind绑定-子应用绑定', { bootstrap: props.bootstrap, mount: props.mount, unmount: props.unmount });
          }
          catch (e) {
              console$1.log('执行绑定微应用失败', { error: e });
          }
      }
      else {
          throw new Error("主应用微应用初始化失败");
      }
  };

  exports.loadMicro = loadMicro;
  exports.microClientBind = microClientBind;
  exports.start = start;

  Object.defineProperty(exports, '__esModule', { value: true });

}));
